﻿// See https://aka.ms/new-console-template for more information
//备忘录模式
//备忘录模式（Memento Pattern）是一种行为型设计模式，他允许你捕获一个对象的内部状态，并在该对象之外保存这个状态，以便之后恢复对象到这个状态。当系统中一个对象需要恢复到某一个历史状态时，就可以使用备忘录模式进行设计。
//备忘录模式主要包含三个部分
//·发起者（Originator）：他是要被保存状态的对象，他有一个内部状态需要保存和恢复。
//·备忘录（Memento）：他是保存发起人的内部状态的对象。
//·管理者（Caretaker）：她负责保存备忘录对象，并提供获取和恢复备忘录对象的方法。
//备忘录模式可以用许多场景，例如游戏存在，编辑器的撤销，重做功能，浏览器的历史记录等。

TextEditor editor = new TextEditor("Hello,world!");
editor.SetText("Hello,Memento!");
editor.SetText("Hello,Design Patterns!");
editor.Undo();
editor.Undo();
editor.Redo();
editor.Redo();


Console.WriteLine("Hello, World!");

//假设有一个文本编辑器，他支持撤销重做操作，当用户进行编辑操作时，系统将自动保存当前编辑器的状态，以便之后可以撤销或者重做。
//发起人类，要被保存的对象
public class TextEditor
{
    private string text;

    public TextEditor(string text)
    {
        this.text = text;
        Caretaker.GetInstance.Save(new Memento(text));
    }

    public void SetText(string text)
    {
        this.text = text;
        Caretaker.GetInstance.Save(new Memento(text));
    }

    public string GetText()
    {
        return text;
    }

    //恢复到备忘录对象所保存的状态
    public void Restore(Memento memento)
    {
        text = Caretaker.GetInstance.Restore(memento).GetText();
    }

    //撤销操作
    public void Undo()
    {
        var m = Caretaker.GetInstance.Undo();
        if (m != null)
        {
            text = m.GetText();
        }
    }

    //重做操作
    public void Redo()
    {
        var m = Caretaker.GetInstance.Redo();
        if (m != null)
        {
            text = m.GetText();
        }
    }
}

//备忘录类
public class Memento
{
    private string text;

    public Memento(string text)
    {
        this.text = text;
    }

    public string GetText()
    {
        return text;
    }
}

//管理者类,管理历史备忘录
public class Caretaker
{
    private List<Memento> history = new List<Memento>();
    private static Caretaker _instance;

    public static Caretaker GetInstance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new Caretaker();
            }
            return _instance;
        }
    }

    //保存备忘录对象
    public void Save(Memento memento)
    {
        history.Add(memento);
        Console.WriteLine("保存状态，文本为：" + memento.GetText());
    }

    //恢复备忘录对象所保存的状态
    public Memento Restore(Memento memento)
    {
        Console.WriteLine("文本恢复为：" + memento.GetText());
        return memento;
    }

    /// <summary>
    /// 撤销操作
    /// </summary>
    /// <returns></returns>
    public Memento Undo()
    {
        Console.WriteLine("文本撤销");
        if (history.Count > 1)
        {
            //此处的操作相当于撤销最后一步
            history.RemoveAt(history.Count - 1);
            return Restore(history[history.Count - 1]);
        }
        else
            return null;
    }

    //重做操作
    public Memento Redo()
    {
        Console.WriteLine("文本重做");
        if (history.Count > 0)
        {
            var m = history[0];
            history.Clear();
            Save(m);
            return Restore(m);
        }
        else
            return null;
    }
}